package restful.struts2;

import static restful.Methods.*;

import java.util.*;
import java.util.regex.*;

import javax.servlet.http.*;

import org.apache.struts2.dispatcher.mapper.*;

import restful.*;

import com.opensymphony.xwork2.config.*;
import com.opensymphony.xwork2.inject.*;

public class RestfulActionMapper extends DefaultActionMapper {

	private RestfulProtocolMatcher mather;

	public RestfulActionMapper() {}

	@Override
	public ActionMapping getMapping(final HttpServletRequest request, final ConfigurationManager configManager) {
		if (mustIgnoreThis(request.getRequestURI())) return super.getMapping(request, configManager);

		final String uri = restfulUri(request);

		final RestfulMethod method = mather.method(ignoreExtension(uri));

		if (method == null) return super.getMapping(request, configManager);

		return new RestfulActionMapping(uri, method);
	}

	private String ignoreExtension(final String uri) {
		for (final String extension : extensions) {
			if (!extension.equals("") && uri.endsWith(extension)) return uri.replaceAll("\\." + extension + "$", "");
		}

		return uri;
	}

	private boolean mustIgnoreThis(final String uri) {
		if (uri.endsWith(".ico")) return true;
		if (uri.endsWith(".css")) return true;
		if (uri.endsWith(".js")) return true;
		if (uri.endsWith(".jpg")) return true;
		if (uri.endsWith(".gif")) return true;
		return false;
	}

	private String pseudoMethodOf(final HttpServletRequest request) {
		final String httpMethod = request.getMethod();
		final String _METHOD = request.getParameter("_METHOD");
		return new OverrideHttpMethod(httpMethod, _METHOD).toString();
	}

	public String restfulUri(final HttpServletRequest request) {
		final String requestURI = request.getRequestURI().replaceAll(request.getContextPath(), "");
		String uri = new Formatter().format("%s %s%s", pseudoMethodOf(request), requestURI, methodOf(request.getQueryString())).toString();
		uri = withoutTransaction(uri);
		return uri;
	}

	@Inject("restfulProtocol")
	public void setRestfulProtocol(final RestfulProtocol restfulProtocol) {
		mather = new RestfulProtocolMatcher().using(restfulProtocol);
	}

	private String withoutTransaction(String uri) {
		if (!uri.matches("^.* /t/[^<>/]*/.*")) return uri;

		final Matcher matcher = Pattern.compile("^.* /t/([^/]*).*").matcher(uri);
		if (matcher.matches()) {
			matcher.group(1);
			uri = uri.replaceAll("/t/[^/]*", "");
		}

		return uri;
	}
}
